// Copyright (c) 2006 Zorm
// Released under the MIT License

#include "PCH.h"
#include "..\Common.h"

bool NIDSParser::LoadFile() {
	if ((m_fileHandle = CreateFile(m_file.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
		DEBUG_LOG("CreateFile failed");
		return false;
	}
	return true;
}

bool NIDSParser::ParseFile() {
	DWORD bytesRead = 0;
	BasicNIDSHeader header;
	BasicNIDSProductDescription productDescription;
	
	//Get rid of WMO header crap
	unsigned char buffer[128] = "";
	int newLines = 0;
	m_startData = 0;
	ZeroMemory(&buffer, 128);
	
	if (!ReadFile(m_fileHandle, &buffer, sizeof(buffer), &bytesRead, NULL) || bytesRead != sizeof(buffer)) {
		DEBUG_LOG("ReadFile buffer failed");
		return false;
	}
	for (int i = 0; i < 128; i++) {
		if (buffer[i] == 0x0D || buffer[i] == 0x0a) {
			newLines++;
			if (newLines == 6) {
				m_startData = i + 1;
				break;
			}
		}	
	}
	if (SetFilePointer(m_fileHandle, m_startData, NULL, FILE_BEGIN) != m_startData) {
		DEBUG_LOG("SetFilePointer data start failed");
		return false;
	}
	
		
	ZeroMemory(&header, sizeof(header));
	bytesRead = 0;
	if (!ReadFile(m_fileHandle, &header, sizeof(header), &bytesRead, NULL) || bytesRead != sizeof(header)) {
		DEBUG_LOG("ReadFile header failed");
		return false;
	}
	
	if (!TranslateHeader(&header)) {
		DEBUG_LOG("TranslateHeader failed");
		return false; //Header data is invalid
	}
	
	if (m_header.numberOfBlocks == 1) {
		DEBUG_LOG("Number of Blocks == 1");
		return false; //Only header block, no data!
	}
	
	ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("%i-%i-%i %02i:%02i:%02i\n"), m_header.messageDate.GetMonth(), m_header.messageDate.GetDay(), m_header.messageDate.GetYear(), m_header.messageTime.GetHours(), m_header.messageTime.GetMinutes(), m_header.messageTime.GetSeconds());
	
	ZeroMemory(&productDescription, sizeof(productDescription));
	bytesRead = 0;
	if (!ReadFile(m_fileHandle, &productDescription, sizeof(productDescription), &bytesRead, NULL) || bytesRead != sizeof(productDescription)) {
		DEBUG_LOG("ReadFile productDescription failed");
		return false;
	}
	
	if (!TranslateProductDescription(&productDescription)) {
		DEBUG_LOG("TranslateProductDescription failed");
		return false;
	}
	
	ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("%i %i %i\n"), m_productDescription.offsetGraphic, m_productDescription.offsetSymbology, m_productDescription.offsetTabular);
	
	if (!ReadSymbologyBlock()) {
		DEBUG_LOG("ReadSymbologyBlock failed");
		return false;
	}
	
	if (!ReadGraphicBlock()) {
		DEBUG_LOG("ReadGraphicBlock failed");
		return false;
	}
	
	if (!ReadTabularBlock()) {
		DEBUG_LOG("ReadTabularBlock failed");
		return false;
	}
	
	return true;
}

bool NIDSParser::ReadSymbologyBlock() {
	DWORD bytesRead = 0;
	BasicNIDSSymbologyBlock symbologyBlock;

	if (m_productDescription.offsetSymbology == 0) {
		DEBUG_LOG("No symbology block");
		return true; //No Symbology block
	}
	
	if (SetFilePointer(m_fileHandle, m_productDescription.offsetSymbology, NULL, FILE_BEGIN) != m_productDescription.offsetSymbology) {
		DEBUG_LOG("SetFilePointer failed");
		return false;
	}
	
	ZeroMemory(&symbologyBlock.Header, sizeof(symbologyBlock.Header));
	if (!ReadFile(m_fileHandle, &symbologyBlock.Header, sizeof(symbologyBlock.Header), &bytesRead, NULL) || bytesRead != sizeof(symbologyBlock.Header)) {
		DEBUG_LOG("ReadFile header failed");
		return false;
	}
	
	if (!TranslateSymbologyHeader(&symbologyBlock)) {
		DEBUG_LOG("TranslateSymbologyHeader failed");
		return false;
	}
	
	for (int i = 0; i < m_symbologyBlock.Header.numberOfLayers; i++) {
		BasicNIDSSymbologyLayer symLayer;
		ZeroMemory(&symLayer, sizeof(symLayer));
		bytesRead = 0;
		if (!ReadFile(m_fileHandle, &symLayer, sizeof(symLayer), &bytesRead, NULL) || bytesRead != sizeof(symLayer)) {
			DEBUG_LOG("ReadFile symbology layer failed");
			return false;
		}
		
		symLayer.layerDivider = _byteswap_ushort(symLayer.layerDivider);
		symLayer.layerLength = _byteswap_ulong(symLayer.layerLength);
		
		if (symLayer.layerDivider != -1) {
			DEBUG_LOG("Invalid layer divider");
			return false;
		}
		
		if (symLayer.layerLength < 1 || symLayer.layerLength > 80000) {
			DEBUG_LOG("Invalid layer length");
			return false;
		}
		
		unsigned char *layerData = new unsigned char[symLayer.layerLength];
		bytesRead = 0;
		ZeroMemory(layerData, symLayer.layerLength);
		if (!ReadFile(m_fileHandle, layerData, symLayer.layerLength, &bytesRead, NULL) || bytesRead != symLayer.layerLength) {
			DEBUG_LOG("ReadFile symbology layer data failed");
			return false;
		}
		
		if (!ParsePacket(layerData, symLayer.layerLength)) {
			DEBUG_LOG("Failed to parse packet data");
			return false;
		}
		
		delete [] layerData;
	}
	
	return true;
}

bool NIDSParser::ReadGraphicBlock() {
	DWORD bytesRead = 0;
	BasicNIDSGraphicBlock graphicBlock;
	
	if (m_productDescription.offsetGraphic == 0) {
		DEBUG_LOG("No graphic block");
		return true;
	}
	
	if (SetFilePointer(m_fileHandle, m_productDescription.offsetGraphic, NULL, FILE_BEGIN) != m_productDescription.offsetGraphic) {
		DEBUG_LOG("SetFilePointer failed");
		return false;
	}
	
	ZeroMemory(&graphicBlock.Header, sizeof(graphicBlock.Header));
	if (!ReadFile(m_fileHandle, &graphicBlock.Header, sizeof(graphicBlock.Header), &bytesRead, NULL) || bytesRead != sizeof(graphicBlock.Header)) {
		DEBUG_LOG("ReadFile header failed");
		return false;
	}
	
	if (!TranslateGraphicHeader(&graphicBlock)) {
		DEBUG_LOG("TranslateGraphicHeader failed");
		return false;
	}
	
	for (int i = 0; i < m_graphicBlock.Header.numberOfPages; i++) {
		BasicNIDSGraphicPage graphicPage;
		ZeroMemory(&graphicPage, sizeof(graphicPage));
		bytesRead = 0;
		if (!ReadFile(m_fileHandle, &graphicPage, sizeof(graphicPage), &bytesRead, NULL) || bytesRead != sizeof(graphicPage)) {
			DEBUG_LOG("ReadFile graphic page failed");
			return false;
		}
		
		graphicPage.pageNumber = _byteswap_ushort(graphicPage.pageNumber);
		graphicPage.pageLength = _byteswap_ushort(graphicPage.pageLength);
		
		if (graphicPage.pageNumber < 1 || graphicPage.pageNumber > 48) {
			DEBUG_LOG("Invalid page number");
			return false;
		}
		
		if (graphicPage.pageLength < 4 || graphicPage.pageLength > 1360) {
			DEBUG_LOG("Invalid page length");
			return false;
		}
		
		unsigned char *pageData = new unsigned char[graphicPage.pageLength];
		bytesRead = 0;
		ZeroMemory(pageData, graphicPage.pageLength);
		if (!ReadFile(m_fileHandle, pageData, graphicPage.pageLength, &bytesRead, NULL) || bytesRead != graphicPage.pageLength) {
			DEBUG_LOG("ReadFile graphic page data failed");
			return false;
		}
		
		if (!ParsePacket(pageData, graphicPage.pageLength)) {
			DEBUG_LOG("Failed to parse packet data");
			return false;
		}
		
		delete [] pageData;
		
	}
	
	return true;
}

bool NIDSParser::ReadTabularBlock() {
	DWORD bytesRead = 0;

	if (m_productDescription.offsetTabular == 0) {
		DEBUG_LOG("No tabular block");
		return true;
	}
	
	if (SetFilePointer(m_fileHandle, m_productDescription.offsetTabular, NULL, FILE_BEGIN) != m_productDescription.offsetTabular) {
		DEBUG_LOG("SetFilePointer failed");
		return false;
	}
	
	#pragma MSG(TODO: Read Tabular Data)
	
	return true;
}

bool NIDSParser::TranslateHeader(BasicNIDSHeader *header) {
	m_header.destID = _byteswap_ushort(header->destID);
	m_header.messageCode = _byteswap_ushort(header->messageCode);
	m_header.messageDate.SetDate(_byteswap_ushort(header->messageDate) + 2440586.5);
	m_header.messageLength = _byteswap_ulong(header->messageLength);
	m_header.messageTime.SetSeconds(_byteswap_ulong(header->messageTime));
	m_header.numberOfBlocks = _byteswap_ushort(header->numberOfBlocks);
	m_header.sourceID = _byteswap_ushort(header->sourceID);
	return true;
}

bool NIDSParser::TranslateSymbologyHeader(BasicNIDSSymbologyBlock *header) {
	m_symbologyBlock.Header.blockDivider = _byteswap_ushort(header->Header.blockDivider);
	m_symbologyBlock.Header.blockID = _byteswap_ushort(header->Header.blockID);
	m_symbologyBlock.Header.blockLength = _byteswap_ulong(header->Header.blockLength);
	m_symbologyBlock.Header.numberOfLayers = _byteswap_ushort(header->Header.numberOfLayers);
	
	if (m_symbologyBlock.Header.blockDivider != -1) {
		DEBUG_LOG("Wrong block divider");
		return false;
	}
	
	if (m_symbologyBlock.Header.blockID != 1) {
		DEBUG_LOG("Wrong symbology block ID");
		return false;
	}
	
	return true;
}

bool NIDSParser::TranslateGraphicHeader(BasicNIDSGraphicBlock *header) {
	m_graphicBlock.Header.blockDivider = _byteswap_ushort(header->Header.blockDivider);
	m_graphicBlock.Header.blockID = _byteswap_ushort(header->Header.blockID);
	m_graphicBlock.Header.blockLength = _byteswap_ulong(header->Header.blockLength);
	m_graphicBlock.Header.numberOfPages = _byteswap_ushort(header->Header.numberOfPages);
	
	if (m_graphicBlock.Header.blockDivider != -1) {
		DEBUG_LOG("Wrong block divider");
		return false;
	}
	
	if (m_graphicBlock.Header.blockID != 2) {
		DEBUG_LOG("Wrong graphic block ID");
		return false;
	}
	
	if (m_graphicBlock.Header.blockLength < 1 || m_graphicBlock.Header.blockLength > 65535) {
		DEBUG_LOG("Invalid block length");
		return false;
	}
	
	if (m_graphicBlock.Header.numberOfPages < 1 || m_graphicBlock.Header.numberOfPages > 48) {
		DEBUG_LOG("Invalid number of pages");
		return false;
	}
	
	return true;
}

bool NIDSParser::TranslateProductDescription(BasicNIDSProductDescription *desc) {
	m_productDescription.blockDivider = _byteswap_ushort(desc->blockDivider);
	if (m_productDescription.blockDivider != -1) {
		DEBUG_LOG("block divider != -1");
		return false;
	}
	
	m_productDescription.dataLevel1 = _byteswap_ushort(desc->dataLevel1);
	m_productDescription.dataLevel2 = _byteswap_ushort(desc->dataLevel2);
	m_productDescription.dataLevel3 = _byteswap_ushort(desc->dataLevel3);
	m_productDescription.dataLevel4 = _byteswap_ushort(desc->dataLevel4);
	m_productDescription.dataLevel5 = _byteswap_ushort(desc->dataLevel5);
	m_productDescription.dataLevel6 = _byteswap_ushort(desc->dataLevel6);
	m_productDescription.dataLevel7 = _byteswap_ushort(desc->dataLevel7);
	m_productDescription.dataLevel8 = _byteswap_ushort(desc->dataLevel8);
	m_productDescription.dataLevel9 = _byteswap_ushort(desc->dataLevel9);
	m_productDescription.dataLevel10 = _byteswap_ushort(desc->dataLevel10);
	m_productDescription.dataLevel11 = _byteswap_ushort(desc->dataLevel11);
	m_productDescription.dataLevel12 = _byteswap_ushort(desc->dataLevel12);
	m_productDescription.dataLevel13 = _byteswap_ushort(desc->dataLevel13);
	m_productDescription.dataLevel14 = _byteswap_ushort(desc->dataLevel14);
	m_productDescription.dataLevel15 = _byteswap_ushort(desc->dataLevel15);
	m_productDescription.dataLevel16 = _byteswap_ushort(desc->dataLevel16);
	m_productDescription.elevationNumber = _byteswap_ushort(desc->elevationNumber);
	m_productDescription.generationDate = _byteswap_ushort(desc->generationDate);
	m_productDescription.generationTime = _byteswap_ulong(desc->generationTime);
	m_productDescription.height = _byteswap_ushort(desc->height);
	m_productDescription.latitude = _byteswap_ulong(desc->latitude) * .001;
	m_productDescription.longitude = long(_byteswap_ulong(desc->longitude)) * .001;
	m_productDescription.numberOfMaps = _byteswap_ushort(desc->numberOfMaps);
	m_productDescription.offsetGraphic = _byteswap_ulong(desc->offsetGraphic) * 2;
	if (m_productDescription.offsetGraphic) {
		m_productDescription.offsetGraphic += m_startData;
	}
	m_productDescription.offsetSymbology = _byteswap_ulong(desc->offsetSymbology) * 2;
	if (m_productDescription.offsetSymbology) {
		m_productDescription.offsetSymbology += m_startData;
	}
	m_productDescription.offsetTabular = _byteswap_ulong(desc->offsetTabular) * 2;
	if (m_productDescription.offsetTabular) {
		m_productDescription.offsetTabular += m_startData;
	}
	m_productDescription.operationalMode = _byteswap_ushort(desc->operationalMode);
	m_productDescription.productCode = _byteswap_ushort(desc->productCode);
	m_productDescription.productDependent1 = _byteswap_ushort(desc->productDependent1);
	m_productDescription.productDependent2 = _byteswap_ushort(desc->productDependent2);
	m_productDescription.productDependent3 = _byteswap_ushort(desc->productDependent3);
	m_productDescription.productDependent4 = _byteswap_ushort(desc->productDependent4);
	m_productDescription.productDependent5 = _byteswap_ushort(desc->productDependent5);
	m_productDescription.productDependent6 = _byteswap_ushort(desc->productDependent6);
	m_productDescription.productDependent7 = _byteswap_ushort(desc->productDependent7);
	m_productDescription.productDependent8 = _byteswap_ushort(desc->productDependent8);
	m_productDescription.productDependent9 = _byteswap_ushort(desc->productDependent9);
	m_productDescription.productDependent10 = _byteswap_ushort(desc->productDependent10);
	m_productDescription.sequenceNumber = _byteswap_ushort(desc->sequenceNumber);
	m_productDescription.volumeCoveragePattern = _byteswap_ushort(desc->volumeCoveragePattern);
	m_productDescription.volumeScanDate = _byteswap_ushort(desc->volumeScanDate);
	m_productDescription.volumeScanNumber = _byteswap_ushort(desc->volumeScanNumber);
	m_productDescription.volumeScanStartTime = _byteswap_ulong(desc->volumeScanStartTime);
	
	return true;
}

bool NIDSParser::ParsePacket(unsigned char *packetData, short length) {

	short currentPosition = 0;
	unsigned char *data = packetData;
	while (length > currentPosition) {
		data = &packetData[currentPosition];
		unsigned short packetID = _byteswap_ushort(*(unsigned short*)data);

		switch (packetID) {
			case NIDSParser::PacketID::WRITESPECIALSYMBOL: {
				short blockLength = _byteswap_ushort(*(short*)(data + 2));
				short IPoint = _byteswap_ushort(*(short*)(data + 4));
				short JPoint = _byteswap_ushort(*(short*)(data + 6));
				unsigned char *text = data + 8;
				ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("(%i, %i) %s\n"), IPoint, JPoint, text);
				currentPosition += blockLength + 4;
				break;
			}
			case NIDSParser::PacketID::MESO: {
				short blockLength = _byteswap_ushort(*(short*)(data + 2));
				short IPoint = _byteswap_ushort(*(short*)(data + 4));
				short JPoint = _byteswap_ushort(*(short*)(data + 6));
				short radius = _byteswap_ushort(*(short*)(data + 8));
				ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("Meso at %i, %i radius %i\n"), IPoint, JPoint, radius);
				currentPosition += blockLength + 4;
				break;
			}
			case NIDSParser::PacketID::WRITETEXTUNIFORM: {
				short blockLength = _byteswap_ushort(*(short*)(data + 2));
				short level = _byteswap_ushort(*(short*)(data + 4));
				short IPoint = _byteswap_ushort(*(short*)(data + 6));
				short JPoint = _byteswap_ushort(*(short*)(data + 8));
				unsigned char *text = data + 10;
				ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("(%i, %i @ %i) %u %s\n"), IPoint, JPoint, level, blockLength, text);
				currentPosition += blockLength + 4;
				break;
			}
			case NIDSParser::PacketID::UNLINKEDVECTORUNIFORM: {
				short blockLength = _byteswap_ushort(*(short*)(data + 2));
				short level = _byteswap_ushort(*(short*)(data + 4));
				short BIPoint1 = _byteswap_ushort(*(short*)(data + 6));
				short BJPoint1 = _byteswap_ushort(*(short*)(data + 8));
				short EIPoint1 = _byteswap_ushort(*(short*)(data + 10));
				short EJPoint1 = _byteswap_ushort(*(short*)(data + 12));
				short BIPoint2 = _byteswap_ushort(*(short*)(data + 6));
				short BJPoint2 = _byteswap_ushort(*(short*)(data + 8));
				short EIPoint2 = _byteswap_ushort(*(short*)(data + 10));
				short EJPoint2 = _byteswap_ushort(*(short*)(data + 12));
				ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("Unlinked vector uniform(%i): %i, %i, %i, %i and %i, %i, %i, %i\n"), level,
				BIPoint1, BJPoint1, EIPoint1, EJPoint1, BIPoint2, BJPoint2, EIPoint2, EJPoint2);
				currentPosition += blockLength + 4;
				break;
			}
			case NIDSParser::PacketID::SHEAR: {
				short blockLength = _byteswap_ushort(*(short*)(data + 2));
				short IPoint = _byteswap_ushort(*(short*)(data + 4));
				short JPoint = _byteswap_ushort(*(short*)(data + 6));
				short radius = _byteswap_ushort(*(short*)(data + 8));
				ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("3DC Shear at %i, %i radius %i\n"), IPoint, JPoint, radius);
				currentPosition += blockLength + 4;
				break;
			}
			case NIDSParser::PacketID::TVS: {
				short blockLength = _byteswap_ushort(*(short*)(data + 2));
				short IPoint = _byteswap_ushort(*(short*)(data + 4));
				short JPoint = _byteswap_ushort(*(short*)(data + 6));
				ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("TVS at %i, %i\n"), IPoint, JPoint);
				currentPosition += blockLength + 4;
				break;
			}
			case NIDSParser::PacketID::HAILPOSITIVE: {
				short blockLength = _byteswap_ushort(*(short*)(data + 2));
				short IPoint = _byteswap_ushort(*(short*)(data + 4));
				short JPoint = _byteswap_ushort(*(short*)(data + 6));
				ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("Hail positive at %i, %i\n"), IPoint, JPoint);
				currentPosition += blockLength + 4;
				break;
			}
			case NIDSParser::PacketID::HAILPROBABLE: {
				short blockLength = _byteswap_ushort(*(short*)(data + 2));
				short IPoint = _byteswap_ushort(*(short*)(data + 4));
				short JPoint = _byteswap_ushort(*(short*)(data + 6));
				ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("Hail probable at %i, %i\n"), IPoint, JPoint);
				currentPosition += blockLength + 4;
				break;
			}
			case NIDSParser::PacketID::STORMID: {
				short blockLength = _byteswap_ushort(*(short*)(data + 2));
				short IPoint = _byteswap_ushort(*(short*)(data + 4));
				short JPoint = _byteswap_ushort(*(short*)(data + 6));
				char char1 = *(char*)(data + 8);
				char char2 = *(char*)(data + 9);
				ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("StormID %c%c at %i, %i\n"), char1, char2, IPoint, JPoint);
				currentPosition += blockLength + 4;
				break;
			}
			case NIDSParser::PacketID::HDAHAIL: {
				short blockLength = _byteswap_ushort(*(short*)(data + 2));
				short IPoint = _byteswap_ushort(*(short*)(data + 4));
				short JPoint = _byteswap_ushort(*(short*)(data + 6));
				short POH = _byteswap_ushort(*(short*)(data + 8));
				short POSH = _byteswap_ushort(*(short*)(data + 10));
				short size = _byteswap_ushort(*(short*)(data + 12));
				ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("Hail at %i, %i, POH: %i%, POSH: %i%, size %i\n"), IPoint, JPoint, POH, POSH, size);
				currentPosition += blockLength + 4;
				break;
			}
			case NIDSParser::PacketID::RADIAL: {
				short indexOfFirstRangeBin = _byteswap_ushort(*(short*)(data + 2));
				short numberOfRangeBins = _byteswap_ushort(*(short*)(data + 4));
				short IPoint = _byteswap_ushort(*(short*)(data + 6));
				short JPoint = _byteswap_ushort(*(short*)(data + 8));
				float scaleFactor = _byteswap_ushort(*(short*)(data + 10)) * .001f;
				short numberOfRadials = _byteswap_ushort(*(short*)(data + 12));
				ATH::Instance()->GetRadarInfo()->SetLatitude(IPoint);
				ATH::Instance()->GetRadarInfo()->SetLongitude(JPoint);
				AlbersToLatLon a2LL = AlbersToLatLon(m_productDescription.latitude + 1.0, m_productDescription.latitude - 1.0, m_productDescription.latitude, m_productDescription.longitude, .999);
				ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("Radial data centered at %i, %i, first bin %i, # bins %i, scale %f, radials %i\n"),
				IPoint, JPoint, indexOfFirstRangeBin, numberOfRangeBins, scaleFactor, numberOfRadials, 270.0 * (M_PI /180.0));
				short dataIndex = 14;
				for (int i = 0; i < numberOfRadials; i++) {
					short radialLength = _byteswap_ushort(*(short*)(data + dataIndex)) * 2;
					dataIndex += 2;
					double radialStartAngle = short(_byteswap_ushort(*(short*)(data + dataIndex))) * 0.1;
					dataIndex += 2;
					double radialDeltaAngle = short(_byteswap_ushort(*(short*)(data + dataIndex))) * 0.1;
					dataIndex += 2;
					short currentRangeBin = indexOfFirstRangeBin;
					double angle1 = 90 - radialStartAngle;
					double angle2 = 90 - (radialStartAngle + radialDeltaAngle);
					bool log = false;
					/*if (angle1 == 270.0 || angle1 == 90.0) {
						ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("1: angle1 %f angle2 %f\n"), angle1, angle2);
						angle1 -= 1;
						log = true;
					}
					if (angle2 == 270.0 || angle2 == 90.0) {
						ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("2: angle1 %f angle2 %f\n"), angle1, angle2);
						angle2 += 1;
						log = true;
					}*/
					angle1 = deg2rad(angle1);
					angle2 = deg2rad(angle2);
					if (currentRangeBin == 0) {
						log = true;
						currentRangeBin = 1;
					}
					for (int j = 0; j < radialLength; j++) {
						char run = (data[dataIndex] & 0xF0) >> 4;
						char level = data[dataIndex] & 0x0F;
						short tempRangeBinLen = currentRangeBin + run;
						if (level == 0) {
							currentRangeBin = tempRangeBinLen;
							dataIndex++;
							continue;
						}
						double x, y, lat, lon;
						PointLatLonR *pt = new PointLatLonR;
						GetCart(currentRangeBin, angle1, &x, &y);
						a2LL.Convert(x, y, &lat, &lon);
//						if (log) ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("%f %f %f %f\n"), x, y, lat, lon);
						/*if (lat == 0) {
							currentRangeBin = tempRangeBinLen;
							dataIndex++;
							continue;
						}*/
						pt->lat[0] = x + IPoint;//int((lat - m_productDescription.latitude) * 100000000.0);
						pt->lon[0] = y + JPoint;//int((lon - m_productDescription.longitude) * 100000000.0);
						//if (log) ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("%i %i %f %f\n"), x, y, lat, lon);
						
						GetCart(tempRangeBinLen, angle1, &x, &y);
						a2LL.Convert(x, y, &lat, &lon);
						pt->lat[1] = x + IPoint;//int((lat - m_productDescription.latitude) * 100000000.0);
						pt->lon[1] = y + JPoint;//int((lon - m_productDescription.longitude) * 100000000.0);
						//if (log) ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("%i %i %f %f\n"), x, y, lat, lon);
						//ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("%f %f\n"), lat, lon);
						
						GetCart(tempRangeBinLen, angle2, &x, &y);
						a2LL.Convert(x, y, &lat, &lon);
						//GetCart(tempRangeBinLen, angle2, &lat, &lon);
						//poCT->Transform(1, &lat, &lon);
						pt->lat[2] = x + IPoint;//int((lat - m_productDescription.latitude) * 100000000.0);
						pt->lon[2] = y + JPoint;//int((lon - m_productDescription.longitude) * 100000000.0);
						//if (log) ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("%i %i %f %f\n"), x, y, lat, lon);
						//ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("%f %f\n"), lat, lon);
						
						GetCart(currentRangeBin, angle2, &x, &y);
						a2LL.Convert(x, y, &lat, &lon);
						//GetCart(currentRangeBin, angle2, &lat, &lon);
						//poCT->Transform(1, &lat, &lon);
						pt->lat[3] = x + IPoint;// int((lat - m_productDescription.latitude) * 100000000.0);
						pt->lon[3] = y + JPoint;//int((lon - m_productDescription.longitude) * 100000000.0);
						//if (log) ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("%i %i %f %f\n"), x, y, lat, lon);
						//ATH::Instance()->GetLog()->LogEvent(Log::LOG_INFO, TEXT("%f %f\n"), lat, lon);
						pt->level = level;
						ATH::Instance()->GetRadarInfo()->GetRadarData()->push_back(pt);
						currentRangeBin = tempRangeBinLen;
						dataIndex++;
					}
				}
				currentPosition = length;
				break;
			}
			default: {
				DEBUG_LOGF("Unknown packet ID 0x%02x", packetID);
				return false; //not really a fatal error
			}
		}
	}
	
	return true;
}

float DegToRad(float deg) {
	const float PI = 2*acos(0.0f);
	return PI;
}